/*********************************************************
 * This application was developed by Monoku (monoku.com)
 * for Google. 
 * @author David Avellaneda / david@monoku.com / @davsket
 * @param {Object} window._IG_Prefs?new_IG_Prefs(
 *********************************************************/
(function(){
	//The languages to apply to the gadget
	var languages = {'EN':'0Asz6kbc7kxOmdGVOZktQV2tPY2gwWnFqZUo5N2kxcmc','ES':'0Asz6kbc7kxOmdHpiSVZmNTJYQ1ZaX0xnWUxsSnI2X3c'};
	
	$('content_div').setStyle('height', $(document.body).getSize().y);
	
	//Markers array for storage and cleaning
	var markersArray = [];
	
	//Default URL for spreadsheets JSONP
	var docs_json_url = 'https://spreadsheets.google.com/feeds/list/$key/$sheet/public/values?alt=json';
	
	//This is to save a default loading of the language
	var lang_dict = {/*No default language*/};
	
	//The States data document key
	var states_doc_key = 'p9CuB_zeAq5X-twnx_mdbKg';
	
	//Prestored coordenades 
	var countriesCoordenades = {'US':{lat:38.5902400,lang:-95.7128910,zoom:3}, 'PE':{lat:-9.1899670,lang:-75.0151520,zoom:4}}
	
	//Stores the States data to load only once
	var states_data = null;
	
	//Tab state
	var last_options_results = 'options';
	//Gadget loaded preferences 
	var prefs = (window._IG_Prefs ? new _IG_Prefs() : {getString: function(){}});
	
	//Base preferences
	var pref = {
		gadgetType: 'iframe',
		address: '',
		fontFamily: 'Verdana, Geneva, Helvetica, sans-serif',
		fontSize: '12',
		country: 'US',
		lang: '0Asz6kbc7kxOmdGVOZktQV2tPY2gwWnFqZUo5N2kxcmc',
		state: '',
		homePrompt: 'Get your voter info! Enter the *full home address* where you&#8217;re registered to vote, including city and state:',
		electionId: '',
		sidebar: false,
		searchMode: 'Address'
	};
	
	//Copy the data
	for( var name in pref ){
		pref[name] = prefs.getString(name) || pref[name];
	} 
	
	//The map element
	var map;
	
	//Users browser language
	var userLang = (navigator.language) ? navigator.language : navigator.userLanguage; 
	userLang = userLang.replace(/[^a-z]+/g, '').toUpperCase().substr(0,2);
	//If exists, is the one applied
	if(languages[userLang]){ 
		pref.lang = languages[userLang];
	}
	
	//The actual state handling, stored as a scoped value
	var selected_state = '';
	
	uiSetup();
	
	function uiSetup(){				
		//Text input listener
		$('keyword').addEvent('keyup', doSearch);
		//Search button listener
		$('search-button').addEvent('click', doSearch);
		
		//Language configuration
		loading();
		var myJSONP = new Request.JSONP({
		    url: docs_json_url.replace('$key',pref.lang).replace('$sheet',1),
		    onComplete: (function(method){
				return function(result){
					method(result);
				}
			})(loadLanguage)
		}).send();
		
		$$('#map-container .header .map').addEvent('click',function(){
			goTo('map');
		});
		
		$$('#map-container .header .result').addEvent('click',function(){
			goTo(last_options_results);
		});
		
		//CSS
		$('widget').setStyle('fontFamily',pref['fontFamily']).setStyle('fontSize',pref['fontSize']);
		
	}
	
	/**
	 * Centers the map according to the country / state
	 * @param {Object} data
	 */
	function centerMapInCountry(data){
		//Map size setting, 32px of padding from the container
		var height = $('widget').getSize().y - $('header').getSize().y - 32;
		$('map').setStyle('height', height);
		//If no global scroll
		//$('vote-data').setStyle('height', height - $$('#results .address')[0].getSize().y);
		
		//Default location
		var latlng = new google.maps.LatLng(37.0902400, -95.7128910);
		
		//Map configuration
	    var myOptions = {
	      zoom: 0,
	      center: latlng,
	      mapTypeId: google.maps.MapTypeId.ROADMAP
	    };
		
		map = new google.maps.Map(document.getElementById('map'), myOptions);
		
		//If there's data, then is the JSONP's callback
		if (data){
			if (pref.state == '') {
				var sq = data.Placemark[0].ExtendedData.LatLonBox;
				var southwest = new google.maps.LatLng(sq.south, sq.west);
				var northeast = new google.maps.LatLng(sq.north, sq.east);
				var bounds = new google.maps.LatLngBounds(southwest, northeast);
				map.fitBounds(bounds);
			}else{
				map.setCenter(new google.maps.LatLng(data.Placemark[0].Point.coordinates[1], data.Placemark[0].Point.coordinates[0]));
				map.setZoom(5);				
			}
			//map.panToBounds(bounds);
			//map.setZoom(map.getZoom()+1);
		}else{
			//If not, we have to check if we do JSONP or is stored
			var cord = countriesCoordenades[pref.country];
			if(cord && pref.state == ''){
				map.setCenter(new google.maps.LatLng(cord.lat, cord.lang));
				map.setZoom(cord.zoom);
				
			}else{
				//Query specification to get the state
				var query = pref.state != '' ? pref.state+' state '+pref.country : pref.country+' country';				
				var myJSONP = new Request.JSONP({
				    url: 'http://maps.google.com/maps/geo?output=json&oe=utf-8&key=ABQIAAAAL7MXzZBubnPtVtBszDCxeRTZqGWfQErE9pT-IucjscazSdFnjBSzjqfxm1CQj7RDgG-OoyNfebJK0w&mapclient=jsapi'+
					'&q='+query,
				    onComplete: (function(method){
						return function(result){
							method(result);
						}
					})(centerMapInCountry)//Recursive calling
				}).send();
			}
		}
	}
	
	function doSearch(ev){
		var value = $("keyword").value;
		var cleanRegex = /[^a-zA-Z0-9\s]/g;
		if((ev.key=='enter'|| ev.target==$('search-button'))&& value.length > 3){
			if(pref['searchMode']=='Address'){
				$$('#options ul')[0].empty();
				loading();
				var myJSONP = new Request.JSONP({
				    url: 'http://maps.google.com/maps/geo?output=json&oe=utf-8&key=ABQIAAAAL7MXzZBubnPtVtBszDCxeRTZqGWfQErE9pT-IucjscazSdFnjBSzjqfxm1CQj7RDgG-OoyNfebJK0w&mapclient=jsapi'+
					'&q='+value,
				    onComplete: (function(method){
						return function(result){
							method(result);
						}
					})(getOptionalAddresses)
				}).send();
			}
			else{ //TODO Else is an id, but id are only numbers
				searchById(value.replace(cleanRegex,''));
			}
		}
	}

	function getOptionalAddresses(options){
		if(options.Status.code == 200 && options.Placemark.length > 0){
			$$('#options h2').setStyle('display','block');
			if(options.Placemark.length>1){ //More than one possible addresses
				goTo('options');
				//remove results outside the country & state
				for(var i=0;i<options.Placemark.length;i++){
					if(options.Placemark[i].AddressDetails.Country.CountryNameCode && options.Placemark[i].AddressDetails.Country.CountryNameCode != pref.country || (pref.state != '' && options.Placemark[i].AddressDetails.Country.AdministrativeArea.AdministrativeAreaName != pref.state)){
						options.Placemark.splice(i,1);
						i--;
					}
				}
				//If no results left
				if(options.Placemark.length==0){
					goTo('options');
					$$('#options h2').setStyle('display','none');
					$$('#options ul')[0].appendChild(new Element('li', {
						html: lang_dict['No results found'], 'class': 'no-results'
					}));
				}else{
					//Print the results
					var fragment = document.createDocumentFragment();
					for(var i=0;i<options.Placemark.length;i++){
						var address = options.Placemark[i].address.replace(', '+options.Placemark[i].AddressDetails.Country.CountryName,'');
						var option = new Element('li', {
							html: '<a href="#">' + address + '</a><input type="hidden" value="'+options.Placemark[i].Point.coordinates[1]+'|'+options.Placemark[i].Point.coordinates[0]+'|'+options.Placemark[i].AddressDetails.Country.AdministrativeArea.AdministrativeAreaName+'" />'
						});
						option.getElement('a').addEvent('click', searchByAddress);
						fragment.appendChild(option);
					}
					$$('#options ul')[0].appendChild(fragment);
				}
			}else if(options.Placemark.length == 1){ //Exact match
				goTo('results');
				var address = options.Placemark[0].address.replace(', '+options.Placemark[0].AddressDetails.Country.CountryName,'');
				if(options.Placemark[0].Point){
					searchByAddress.bind({innerHTML:address, geoData: options.Placemark[0].Point.coordinates[1]+'|'+options.Placemark[0].Point.coordinates[0]+'|'+options.Placemark[0].AddressDetails.Country.AdministrativeArea.AdministrativeAreaName})();
				}
			}
		}else{
			goTo('options');
			$$('#options h2').setStyle('display','none');
			$$('#options ul')[0].appendChild(new Element('li', {
				html: lang_dict['No results found'], 'class': 'no-results'
			}));
		}
		unload();
	}
	
	function goTo(section){
		$$('#map-container .header .map, #map-container .header .result').removeClass('selected');
		if(section!='map'){
			last_options_results=section;
			$$('#map-container .header .result').removeClass('hidden').addClass('selected');
		}else{
			$$('#map-container .header .map').addClass('selected');
		}
		$$('#results, #options').setStyle('display', 'none');
		$(section).setStyle('display', 'block');
	}
	
	function loadLanguage(language){
		var values = language.feed.entry;
		for(var i=0; i<values.length; i++){
			lang_dict[values[i]['gsx$value']['$t']]=values[i]['gsx$translation']['$t'];
		}
		
		//Apply translation
		//Title
		$$('#header h1')[0].set('html',lang_dict['title']);
		//Intro
		$$('#header .intro')[0].set('html',lang_dict['intro']);
		//Example
		if(pref['searchMode']=='Address'){
			$('keyword').set('placeholder',lang_dict['example address']);
		}else{
			$('keyword').set('placeholder',lang_dict['example id']);
		}
		//Map/title
		$$('#map-container .map a')[0].set('html',lang_dict['Map']);
		//Result/title
		$$('#map-container .result a')[0].set('html',lang_dict['Result']);
		//Did you mean
		$$('#options h2')[0].set('html',lang_dict['Did you mean']);
		//Your data
		$$('#results .address h2')[0].set('html',lang_dict['Your data']);
		
		$('header').setStyle('visibility', 'visible');
		
		centerMapInCountry();
		
		unload();
	}
	
	function searchByAddress(){
		var address = this.innerHTML;
		$$('#results .address h3').set('html', address);
		loading();
		//Retrieve the data related to the address the user selected
		var values;
		if(this.geoData){
			values = this.geoData.split('|');
		}else{
			values = this.parentNode.getElementsByTagName('input')[0].value.split('|');
		}
		
		var lat = values[0];
		var lang = values[1];
		selected_state = values[2];
		
  		//The user address latlang
		var userAddress = new google.maps.LatLng(parseFloat(lat), parseFloat(lang));

		//Cleaning the map and centering
		cleanMapMarkers();
		map.setCenter(userAddress);
		map.setZoom(14);
		
		//Doing the marker
		var marker = new google.maps.Marker({
		    position: userAddress,
		    map: map, 
      		title: address,
			icon: 'http://gavella-monoku-election.googlecode.com/hg/new-voter-info/img/person.png'
		});
		
		var infoWindow = new google.maps.InfoWindow();
		infoWindow.setOptions({position: userAddress, content: '<p class="infowindow" style="padding: 20px 5px 0;">'+address+'</p>'});
		google.maps.event.addListener(marker, 'click', function(){
			infoWindow.open(map, marker);
	    });
		
		markersArray.push(marker, marker);
		
				
		var myJSONP = new Request.JSONP({
		    url: 'http://pollinglocation.apis.google.com/?q='+address,
			callbackKey: 'jsonp',
		    onComplete: (function(method){
				return function(result){
					method(result);
				}
			})(getLocations)
		}).send();
	}
	
	function searchById(id){
		//Clean the map
		cleanMapMarkers();
		loading();
		$$('#results .address h3').set('html', id);
		var myJSONP = new Request.JSONP({
		    url: 'http://pollinglocation.apis.google.com/?electionid=-1000000&q='+id,
			callbackKey: 'jsonp',
		    onComplete: (function(method){
				return function(result){
					method(result);
				}
			})(getLocations)
		}).send();
	}
	
	function getLocations(obj){
		goTo('results');
		var wrapper = $$('#vote-data .wrapper')[0];
		wrapper.empty();
		if (obj.locations.length > 0 && obj.locations[0].length > 0) {
			for (var i = 0; i < obj.locations.length; i++) {
				for (var j = 0; j < obj.locations[i].length; j++) {
					//If exists a point in the map...
					if(obj.locations[i][j].latitude){
						var userAddress = new google.maps.LatLng(obj.locations[i][j].latitude,obj.locations[i][j].longitude);
						var marker = new google.maps.Marker({
						    position: userAddress,
						    map: map, 
				      		title: obj.locations[i][j].address.location_name+': '+full_address,
							icon: 'http://gavella-monoku-election.googlecode.com/hg/new-voter-info/img/voter-place.png'
						});
						markersArray.push(marker);
						
						//Centering the map
						map.setCenter(userAddress);
						map.setZoom(14);
						
						//Infowindow
						var infoWindow = new google.maps.InfoWindow();
						infoWindow.setOptions({position: userAddress, content: '<p class="infowindow" style="padding: 20px 5px 0;">'+obj.locations[i][j].address.location_name+': '+full_address+'</p>'});
						google.maps.event.addListener(marker, 'click', function(){
							infoWindow.open(map, marker);
					    });
						wrapper.adopt(new Element('a', {
							html: lang_dict['View on the map'], 
							'class': 'go-map',  
							events: {
						        click: function(){
						            goTo('map');
						        }
						    }
						}));
						var padding_container = new Element('div', {
							'class': 'padding'
						})
						wrapper.adopt(padding_container);
						wrapper = padding_container;
					}
					
					if (i == 0 && j == 0) {
						wrapper.adopt(new Element('h4', {
							html: lang_dict['Check your voting location on your state']}));
					}

					wrapper.adopt(new Element('h5', {
						html: obj.locations[i][j].address.location_name + ' (' + obj.locations[i][j].id + ')'}));
					
					selected_state = obj.locations[i][j].address.state;
					
					var full_address = obj.locations[i][j].address.line1 + ", " + obj.locations[i][j].address.city +
						(obj.locations[i][j].address.state ? ", " + obj.locations[i][j].address.state : "")+
						(obj.locations[i][j].address.county ? ", " + obj.locations[i][j].address.county : "")+
						(obj.locations[i][j].address.zip ? ", " + obj.locations[i][j].address.zip : "");
						
					wrapper.adopt(new Element('p', {html: full_address}));
					
					if(obj.locations[i][j].polling_hours){
						wrapper.adopt(new Element('p', {html: obj.locations[i][j].polling_hours}));
					}
					$$('#vote-data  .wrapper')[0].adopt(new Element('div', {'class': 'clear'}));
				}
			}
		}else if(selected_state == ''){
			goTo('results');
			$$('#vote-data  .wrapper')[0].empty();
			$$('#vote-data  .wrapper')[0].appendChild(new Element('p', {
				html: lang_dict['No results found'], 'class': 'no-results'
			}));
			unload();
			return false;
		}
		
		
		if(obj.locations[0][0]&& obj.locations[0][0].address){
			selected_state = obj.locations[0][0].address.state;
		}
		
		//If it's United States the state data is pulled from the sheet
		if(pref.country == 'US'){
			if (states_data == null) {
				var myJSONP = new Request.JSONP({
				    url: docs_json_url.replace('$key',states_doc_key).replace('$sheet',2),
				    onComplete: (function(method){
						return function(result){
							method(result);
						}
					})(loadUSStateVoterData)
				}).send();
			}else{
				fillStateData();
			}
		}else{
			fillStateData();
			unload();
		}		
	}
	
	function loadUSStateVoterData(data){
		var values = data.feed.entry;
		states_data = {};
		for(var i=0; i<values.length; i++){
			states_data[values[i]['gsx$abbr']['$t']]={
				'name': values[i]['gsx$name']['$t'],
				'areyouregistered': values[i]['gsx$areyouregistered']['$t'],
				'registrationinfo': values[i]['gsx$registrationinfo']['$t'],
				'absenteeinfo': values[i]['gsx$absenteeinfo']['$t'],
				'inpersoninfo': values[i]['gsx$inpersoninfo']['$t'],
				'wheretovote': values[i]['gsx$wheretovote']['$t'],
				'electionwebsite': values[i]['gsx$electionwebsite']['$t'],
				'hotline': values[i]['gsx$hotline']['$t']
			};
		}
		unload();
		fillStateData();
	}
	
	function fillStateData(){
		var wrapper = $$('#vote-data .wrapper')[0];
		if(states_data && selected_state!='' && states_data[selected_state]){
			if (states_data[selected_state].wheretovote != '') {
				wrapper.adopt(new Element('p', {
					html: lang_dict['Check your voting location on your state'] + ' <a target="_blank" href="' + states_data[selected_state].wheretovote + '">' + lang_dict['voting place locator'] + '</a>'
				}));
			}
					
			wrapper.adopt(new Element('h4', {
				html: lang_dict['How to vote in']+" "+states_data[selected_state].name
				}));
				
			if (states_data[selected_state].electionwebsite != '') {
				wrapper.adopt(new Element('p', {
					html: '<a target="_blank" href="' + states_data[selected_state].electionwebsite + '">' + states_data[selected_state].name + ' ' + lang_dict['election website'] + '</a>'
				}));
			}
					
			if (states_data[selected_state].areyouregistered != '') {
				wrapper.adopt(new Element('p', {
					html: '<a target="_blank" href="' + states_data[selected_state].areyouregistered + '">' + lang_dict['Are you registered to vote?'] + '</a>'
				}));
			}
			
			if(states_data[selected_state].absenteeinfo != ''){
				wrapper.adopt(new Element('p', {
					html: lang_dict['Some $state voters may qualify to vote by mail.'].replace('$state', states_data[selected_state].name)
					}));
				wrapper.adopt(new Element('p', {
					html: '<a target="_blank" href="'+states_data[selected_state].absenteeinfo+'">'+lang_dict['Get an absentee ballot']+'</a>'
					}));
			}
			
			if (states_data[selected_state].hotline != '') {
				wrapper.adopt(new Element('p', {
					html: lang_dict['$state voter hotline: $phone'].replace('$state', states_data[selected_state].name).replace('$phone', states_data[selected_state].hotline)
				}));
			}
		}
		
			
		wrapper.adopt(new Element('p', {
			html: '<a target="_blank" href="http://spreadsheets.google.com/viewform?formkey=dG5rTHNRNWVYdGYwMmFjbDBydzlLR2c6MA">'+lang_dict['Report an error']+'</a>'
			}));
	}
	
	function loading(){
		$('loading').setStyle('display','block');
		$('keyword').set('disabled', true);
		$('search-button').set('disabled', true);
	}
	
	function unload(){
		$('loading').setStyle('display','none');
		$('keyword').set('disabled', false);
		$('search-button').set('disabled', false);
	}
	
	function cleanMapMarkers(){
		while(markersArray.length > 0){
			markersArray.shift().setMap(null);
		}
	}
})();